{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ECOモデルの実装\n",
    "本ファイルでは、ECOモデルを実装します。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 9.2 学習目標\n",
    "\n",
    "1.\tECOの2D Netモジュールの概要を理解する\n",
    "2.\tInception-v2を実装できるようになる\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 9.3 学習目標\n",
    "\n",
    "1.\tECOの3D Netモジュールの概要を理解する\n",
    "2.\t3D Resnetを実装できるようになる\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 事前準備\n",
    "\n",
    "とくになし"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch import nn"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ECOの2D Netモジュール"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class BasicConv(nn.Module):\n",
    "    '''ECOの2D Netモジュールの最初のモジュール'''\n",
    "\n",
    "    def __init__(self):\n",
    "        super(BasicConv, self).__init__()\n",
    "\n",
    "        self.conv1_7x7_s2 = nn.Conv2d(3, 64, kernel_size=(\n",
    "            7, 7), stride=(2, 2), padding=(3, 3))\n",
    "        self.conv1_7x7_s2_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.conv1_relu_7x7 = nn.ReLU(inplace=True)\n",
    "        self.pool1_3x3_s2 = nn.MaxPool2d(\n",
    "            kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)\n",
    "        self.conv2_3x3_reduce = nn.Conv2d(\n",
    "            64, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.conv2_3x3_reduce_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.conv2_relu_3x3_reduce = nn.ReLU(inplace=True)\n",
    "        self.conv2_3x3 = nn.Conv2d(64, 192, kernel_size=(\n",
    "            3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.conv2_3x3_bn = nn.BatchNorm2d(\n",
    "            192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.conv2_relu_3x3 = nn.ReLU(inplace=True)\n",
    "        self.pool2_3x3_s2 = nn.MaxPool2d(\n",
    "            kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)\n",
    "\n",
    "    def forward(self, x):\n",
    "        out = self.conv1_7x7_s2(x)\n",
    "        out = self.conv1_7x7_s2_bn(out)\n",
    "        out = self.conv1_relu_7x7(out)\n",
    "        out = self.pool1_3x3_s2(out)\n",
    "        out = self.conv2_3x3_reduce(out)\n",
    "        out = self.conv2_3x3_reduce_bn(out)\n",
    "        out = self.conv2_relu_3x3_reduce(out)\n",
    "        out = self.conv2_3x3(out)\n",
    "        out = self.conv2_3x3_bn(out)\n",
    "        out = self.conv2_relu_3x3(out)\n",
    "        out = self.pool2_3x3_s2(out)\n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class InceptionA(nn.Module):\n",
    "    '''InceptionA'''\n",
    "\n",
    "    def __init__(self):\n",
    "        super(InceptionA, self).__init__()\n",
    "\n",
    "        self.inception_3a_1x1 = nn.Conv2d(\n",
    "            192, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3a_1x1_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3a_relu_1x1 = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.inception_3a_3x3_reduce = nn.Conv2d(\n",
    "            192, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3a_3x3_reduce_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3a_relu_3x3_reduce = nn.ReLU(inplace=True)\n",
    "        self.inception_3a_3x3 = nn.Conv2d(\n",
    "            64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.inception_3a_3x3_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3a_relu_3x3 = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.inception_3a_double_3x3_reduce = nn.Conv2d(\n",
    "            192, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3a_double_3x3_reduce_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3a_relu_double_3x3_reduce = nn.ReLU(inplace=True)\n",
    "        self.inception_3a_double_3x3_1 = nn.Conv2d(\n",
    "            64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.inception_3a_double_3x3_1_bn = nn.BatchNorm2d(\n",
    "            96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3a_relu_double_3x3_1 = nn.ReLU(inplace=True)\n",
    "        self.inception_3a_double_3x3_2 = nn.Conv2d(\n",
    "            96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.inception_3a_double_3x3_2_bn = nn.BatchNorm2d(\n",
    "            96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3a_relu_double_3x3_2 = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.inception_3a_pool = nn.AvgPool2d(\n",
    "            kernel_size=3, stride=1, padding=1)\n",
    "        self.inception_3a_pool_proj = nn.Conv2d(\n",
    "            192, 32, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3a_pool_proj_bn = nn.BatchNorm2d(\n",
    "            32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3a_relu_pool_proj = nn.ReLU(inplace=True)\n",
    "\n",
    "    def forward(self, x):\n",
    "\n",
    "        out1 = self.inception_3a_1x1(x)\n",
    "        out1 = self.inception_3a_1x1_bn(out1)\n",
    "        out1 = self.inception_3a_relu_1x1(out1)\n",
    "\n",
    "        out2 = self.inception_3a_3x3_reduce(x)\n",
    "        out2 = self.inception_3a_3x3_reduce_bn(out2)\n",
    "        out2 = self.inception_3a_relu_3x3_reduce(out2)\n",
    "        out2 = self.inception_3a_3x3(out2)\n",
    "        out2 = self.inception_3a_3x3_bn(out2)\n",
    "        out2 = self.inception_3a_relu_3x3(out2)\n",
    "\n",
    "        out3 = self.inception_3a_double_3x3_reduce(x)\n",
    "        out3 = self.inception_3a_double_3x3_reduce_bn(out3)\n",
    "        out3 = self.inception_3a_relu_double_3x3_reduce(out3)\n",
    "        out3 = self.inception_3a_double_3x3_1(out3)\n",
    "        out3 = self.inception_3a_double_3x3_1_bn(out3)\n",
    "        out3 = self.inception_3a_relu_double_3x3_1(out3)\n",
    "        out3 = self.inception_3a_double_3x3_2(out3)\n",
    "        out3 = self.inception_3a_double_3x3_2_bn(out3)\n",
    "        out3 = self.inception_3a_relu_double_3x3_2(out3)\n",
    "\n",
    "        out4 = self.inception_3a_pool(x)\n",
    "        out4 = self.inception_3a_pool_proj(out4)\n",
    "        out4 = self.inception_3a_pool_proj_bn(out4)\n",
    "        out4 = self.inception_3a_relu_pool_proj(out4)\n",
    "\n",
    "        outputs = [out1, out2, out3, out4]\n",
    "\n",
    "        return torch.cat(outputs, 1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class InceptionB(nn.Module):\n",
    "    '''InceptionB'''\n",
    "\n",
    "    def __init__(self):\n",
    "        super(InceptionB, self).__init__()\n",
    "        \n",
    "        self.inception_3b_1x1 = nn.Conv2d(\n",
    "            256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3b_1x1_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3b_relu_1x1 = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.inception_3b_3x3_reduce = nn.Conv2d(\n",
    "            256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3b_3x3_reduce_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3b_relu_3x3_reduce = nn.ReLU(inplace=True)\n",
    "        self.inception_3b_3x3 = nn.Conv2d(\n",
    "            64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.inception_3b_3x3_bn = nn.BatchNorm2d(\n",
    "            96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3b_relu_3x3 = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.inception_3b_double_3x3_reduce = nn.Conv2d(\n",
    "            256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3b_double_3x3_reduce_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3b_relu_double_3x3_reduce = nn.ReLU(inplace=True)\n",
    "        self.inception_3b_double_3x3_1 = nn.Conv2d(\n",
    "            64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.inception_3b_double_3x3_1_bn = nn.BatchNorm2d(\n",
    "            96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3b_relu_double_3x3_1 = nn.ReLU(inplace=True)\n",
    "        self.inception_3b_double_3x3_2 = nn.Conv2d(\n",
    "            96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.inception_3b_double_3x3_2_bn = nn.BatchNorm2d(\n",
    "            96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3b_relu_double_3x3_2 = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.inception_3b_pool = nn.AvgPool2d(\n",
    "            kernel_size=3, stride=1, padding=1)\n",
    "        self.inception_3b_pool_proj = nn.Conv2d(\n",
    "            256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3b_pool_proj_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3b_relu_pool_proj = nn.ReLU(inplace=True)\n",
    "\n",
    "    def forward(self, x):\n",
    "        \n",
    "        out1 = self.inception_3b_1x1(x)\n",
    "        out1 = self.inception_3b_1x1_bn(out1)\n",
    "        out1 = self.inception_3b_relu_1x1(out1)\n",
    "\n",
    "        out2 = self.inception_3b_3x3_reduce(x)\n",
    "        out2 = self.inception_3b_3x3_reduce_bn(out2)\n",
    "        out2 = self.inception_3b_relu_3x3_reduce(out2)\n",
    "        out2 = self.inception_3b_3x3(out2)\n",
    "        out2 = self.inception_3b_3x3_bn(out2)\n",
    "        out2 = self.inception_3b_relu_3x3(out2)\n",
    "\n",
    "        out3 = self.inception_3b_double_3x3_reduce(x)\n",
    "        out3 = self.inception_3b_double_3x3_reduce_bn(out3)\n",
    "        out3 = self.inception_3b_relu_double_3x3_reduce(out3)\n",
    "        out3 = self.inception_3b_double_3x3_1(out3)\n",
    "        out3 = self.inception_3b_double_3x3_1_bn(out3)\n",
    "        out3 = self.inception_3b_relu_double_3x3_1(out3)\n",
    "        out3 = self.inception_3b_double_3x3_2(out3)\n",
    "        out3 = self.inception_3b_double_3x3_2_bn(out3)\n",
    "        out3 = self.inception_3b_relu_double_3x3_2(out3)\n",
    "\n",
    "        out4 = self.inception_3b_pool(x)\n",
    "        out4 = self.inception_3b_pool_proj(out4)\n",
    "        out4 = self.inception_3b_pool_proj_bn(out4)\n",
    "        out4 = self.inception_3b_relu_pool_proj(out4)\n",
    "\n",
    "        outputs = [out1, out2, out3, out4]\n",
    "\n",
    "        return torch.cat(outputs, 1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class InceptionC(nn.Module):\n",
    "    '''InceptionC'''\n",
    "\n",
    "    def __init__(self):\n",
    "        super(InceptionC, self).__init__()\n",
    "\n",
    "        self.inception_3c_double_3x3_reduce = nn.Conv2d(\n",
    "            320, 64, kernel_size=(1, 1), stride=(1, 1))\n",
    "        self.inception_3c_double_3x3_reduce_bn = nn.BatchNorm2d(\n",
    "            64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3c_relu_double_3x3_reduce = nn.ReLU(inplace=True)\n",
    "        self.inception_3c_double_3x3_1 = nn.Conv2d(\n",
    "            64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
    "        self.inception_3c_double_3x3_1_bn = nn.BatchNorm2d(\n",
    "            96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.inception_3c_relu_double_3x3_1 = nn.ReLU(inplace=True)\n",
    "\n",
    "    def forward(self, x):\n",
    "        out = self.inception_3c_double_3x3_reduce(x)\n",
    "        out = self.inception_3c_double_3x3_reduce_bn(out)\n",
    "        out = self.inception_3c_relu_double_3x3_reduce(out)\n",
    "        out = self.inception_3c_double_3x3_1(out)\n",
    "        out = self.inception_3c_double_3x3_1_bn(out)\n",
    "        out = self.inception_3c_relu_double_3x3_1(out)\n",
    "\n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ECO_2D(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(ECO_2D, self).__init__()\n",
    "\n",
    "        # BasicConvモジュール\n",
    "        self.basic_conv = BasicConv()\n",
    "\n",
    "        # Inceptionモジュール\n",
    "        self.inception_a = InceptionA()\n",
    "        self.inception_b = InceptionB()\n",
    "        self.inception_c = InceptionC()\n",
    "\n",
    "    def forward(self, x):\n",
    "        '''\n",
    "        入力xのサイズtorch.Size([batch_num, 3, 224, 224]))\n",
    "        '''\n",
    "        out = self.basic_conv(x)\n",
    "        out = self.inception_a(out)\n",
    "        out = self.inception_b(out)\n",
    "        out = self.inception_c(out)\n",
    "\n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 動作確認"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ECO_2D(\n",
       "  (basic_conv): BasicConv(\n",
       "    (conv1_7x7_s2): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))\n",
       "    (conv1_7x7_s2_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (conv1_relu_7x7): ReLU(inplace)\n",
       "    (pool1_3x3_s2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)\n",
       "    (conv2_3x3_reduce): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (conv2_3x3_reduce_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (conv2_relu_3x3_reduce): ReLU(inplace)\n",
       "    (conv2_3x3): Conv2d(64, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (conv2_3x3_bn): BatchNorm2d(192, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (conv2_relu_3x3): ReLU(inplace)\n",
       "    (pool2_3x3_s2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)\n",
       "  )\n",
       "  (inception_a): InceptionA(\n",
       "    (inception_3a_1x1): Conv2d(192, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3a_1x1_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3a_relu_1x1): ReLU(inplace)\n",
       "    (inception_3a_3x3_reduce): Conv2d(192, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3a_3x3_reduce_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3a_relu_3x3_reduce): ReLU(inplace)\n",
       "    (inception_3a_3x3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (inception_3a_3x3_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3a_relu_3x3): ReLU(inplace)\n",
       "    (inception_3a_double_3x3_reduce): Conv2d(192, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3a_double_3x3_reduce_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3a_relu_double_3x3_reduce): ReLU(inplace)\n",
       "    (inception_3a_double_3x3_1): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (inception_3a_double_3x3_1_bn): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3a_relu_double_3x3_1): ReLU(inplace)\n",
       "    (inception_3a_double_3x3_2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (inception_3a_double_3x3_2_bn): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3a_relu_double_3x3_2): ReLU(inplace)\n",
       "    (inception_3a_pool): AvgPool2d(kernel_size=3, stride=1, padding=1)\n",
       "    (inception_3a_pool_proj): Conv2d(192, 32, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3a_pool_proj_bn): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3a_relu_pool_proj): ReLU(inplace)\n",
       "  )\n",
       "  (inception_b): InceptionB(\n",
       "    (inception_3b_1x1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3b_1x1_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3b_relu_1x1): ReLU(inplace)\n",
       "    (inception_3b_3x3_reduce): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3b_3x3_reduce_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3b_relu_3x3_reduce): ReLU(inplace)\n",
       "    (inception_3b_3x3): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (inception_3b_3x3_bn): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3b_relu_3x3): ReLU(inplace)\n",
       "    (inception_3b_double_3x3_reduce): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3b_double_3x3_reduce_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3b_relu_double_3x3_reduce): ReLU(inplace)\n",
       "    (inception_3b_double_3x3_1): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (inception_3b_double_3x3_1_bn): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3b_relu_double_3x3_1): ReLU(inplace)\n",
       "    (inception_3b_double_3x3_2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (inception_3b_double_3x3_2_bn): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3b_relu_double_3x3_2): ReLU(inplace)\n",
       "    (inception_3b_pool): AvgPool2d(kernel_size=3, stride=1, padding=1)\n",
       "    (inception_3b_pool_proj): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3b_pool_proj_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3b_relu_pool_proj): ReLU(inplace)\n",
       "  )\n",
       "  (inception_c): InceptionC(\n",
       "    (inception_3c_double_3x3_reduce): Conv2d(320, 64, kernel_size=(1, 1), stride=(1, 1))\n",
       "    (inception_3c_double_3x3_reduce_bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3c_relu_double_3x3_reduce): ReLU(inplace)\n",
       "    (inception_3c_double_3x3_1): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "    (inception_3c_double_3x3_1_bn): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (inception_3c_relu_double_3x3_1): ReLU(inplace)\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# モデルの用意\n",
    "net = ECO_2D()\n",
    "net.train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. tensorboardXの保存クラスを呼び出します\n",
    "from tensorboardX import SummaryWriter\n",
    "\n",
    "# 2. フォルダ「tbX」に保存させるwriterを用意します\n",
    "# フォルダ「tbX」はなければ自動で作成されます\n",
    "writer = SummaryWriter(\"./tbX/\")\n",
    "\n",
    "\n",
    "# 3. ネットワークに流し込むダミーデータを作成します\n",
    "batch_size = 1\n",
    "dummy_img = torch.rand(batch_size, 3, 224, 224)\n",
    "\n",
    "# 4. netに対して、ダミーデータである\n",
    "# dummy_imgを流したときのgraphをwriterに保存させます\n",
    "writer.add_graph(net, (dummy_img, ))\n",
    "writer.close()\n",
    "\n",
    "\n",
    "# 5. コマンドプロンプトを開き、フォルダtbXがあるフォルダまで移動して、\n",
    "# 以下のコマンドを実行します\n",
    "\n",
    "# tensorboard --logdir=\"./tbX/\"\n",
    "\n",
    "# その後、http://localhost:6006 にアクセスします\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ECOの3D Netモジュール"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Resnet_3D_3(nn.Module):\n",
    "    '''Resnet_3D_3'''\n",
    "\n",
    "    def __init__(self):\n",
    "        super(Resnet_3D_3, self).__init__()\n",
    "        \n",
    "        self.res3a_2 = nn.Conv3d(96, 128, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res3a_bn = nn.BatchNorm3d(\n",
    "            128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res3a_relu = nn.ReLU(inplace=True)\n",
    "\n",
    "        self.res3b_1 = nn.Conv3d(128, 128, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        self.res3b_1_bn = nn.BatchNorm3d(\n",
    "            128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res3b_1_relu = nn.ReLU(inplace=True)\n",
    "        self.res3b_2 = nn.Conv3d(128, 128, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res3b_bn = nn.BatchNorm3d(\n",
    "            128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res3b_relu = nn.ReLU(inplace=True)\n",
    "\n",
    "    def forward(self, x):\n",
    "\n",
    "        residual = self.res3a_2(x)\n",
    "        out = self.res3a_bn(residual)\n",
    "        out = self.res3a_relu(out)\n",
    "\n",
    "        out = self.res3b_1(out)\n",
    "        out = self.res3b_1_bn(out)\n",
    "        out = self.res3b_relu(out)\n",
    "        out = self.res3b_2(out)\n",
    "\n",
    "        out += residual\n",
    "\n",
    "        out = self.res3b_bn(out)\n",
    "        out = self.res3b_relu(out)\n",
    "\n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Resnet_3D_4(nn.Module):\n",
    "    '''Resnet_3D_4'''\n",
    "\n",
    "    def __init__(self):\n",
    "        super(Resnet_3D_4, self).__init__()\n",
    "\n",
    "        self.res4a_1 = nn.Conv3d(128, 256, kernel_size=(\n",
    "            3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
    "        self.res4a_1_bn = nn.BatchNorm3d(\n",
    "            256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res4a_1_relu = nn.ReLU(inplace=True)\n",
    "        self.res4a_2 = nn.Conv3d(256, 256, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res4a_down = nn.Conv3d(128, 256, kernel_size=(\n",
    "            3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res4a_bn = nn.BatchNorm3d(\n",
    "            256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res4a_relu = nn.ReLU(inplace=True)\n",
    "        \n",
    "        self.res4b_1 = nn.Conv3d(256, 256, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        self.res4b_1_bn = nn.BatchNorm3d(\n",
    "            256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res4b_1_relu = nn.ReLU(inplace=True)\n",
    "        self.res4b_2 = nn.Conv3d(256, 256, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res4b_bn = nn.BatchNorm3d(\n",
    "            256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res4b_relu = nn.ReLU(inplace=True)\n",
    "\n",
    "    def forward(self, x):\n",
    "        residual = self.res4a_down(x)\n",
    "\n",
    "        out = self.res4a_1(x)\n",
    "        out = self.res4a_1_bn(out)\n",
    "        out = self.res4a_1_relu(out)\n",
    "\n",
    "        out = self.res4a_2(out)\n",
    "\n",
    "        out += residual\n",
    "\n",
    "        residual2 = out\n",
    "\n",
    "        out = self.res4a_bn(out)\n",
    "        out = self.res4a_relu(out)\n",
    "\n",
    "        out = self.res4b_1(out)\n",
    "\n",
    "        out = self.res4b_1_bn(out)\n",
    "        out = self.res4b_1_relu(out)\n",
    "\n",
    "        out = self.res4b_2(out)\n",
    "\n",
    "        out += residual2\n",
    "\n",
    "        out = self.res4b_bn(out)\n",
    "        out = self.res4b_relu(out)\n",
    "\n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Resnet_3D_5(nn.Module):\n",
    "    '''Resnet_3D_5'''\n",
    "\n",
    "    def __init__(self):\n",
    "        super(Resnet_3D_5, self).__init__()\n",
    "        \n",
    "        self.res5a_1 = nn.Conv3d(256, 512, kernel_size=(\n",
    "            3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
    "        self.res5a_1_bn = nn.BatchNorm3d(\n",
    "            512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res5a_1_relu = nn.ReLU(inplace=True)\n",
    "        self.res5a_2 = nn.Conv3d(512, 512, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res5a_down = nn.Conv3d(256, 512, kernel_size=(\n",
    "            3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res5a_bn = nn.BatchNorm3d(\n",
    "            512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res5a_relu = nn.ReLU(inplace=True)\n",
    "        \n",
    "        self.res5b_1 = nn.Conv3d(512, 512, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        self.res5b_1_bn = nn.BatchNorm3d(\n",
    "            512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res5b_1_relu = nn.ReLU(inplace=True)\n",
    "        self.res5b_2 = nn.Conv3d(512, 512, kernel_size=(\n",
    "            3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
    "        \n",
    "        self.res5b_bn = nn.BatchNorm3d(\n",
    "            512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
    "        self.res5b_relu = nn.ReLU(inplace=True)\n",
    "\n",
    "    def forward(self, x):\n",
    "        residual = self.res5a_down(x)\n",
    "\n",
    "        out = self.res5a_1(x)\n",
    "        out = self.res5a_1_bn(out)\n",
    "        out = self.res5a_1_relu(out)\n",
    "\n",
    "        out = self.res5a_2(out)\n",
    "\n",
    "        out += residual  # res5a\n",
    "\n",
    "        residual2 = out\n",
    "\n",
    "        out = self.res5a_bn(out)\n",
    "        out = self.res5a_relu(out)\n",
    "\n",
    "        out = self.res5b_1(out)\n",
    "\n",
    "        out = self.res5b_1_bn(out)\n",
    "        out = self.res5b_1_relu(out)\n",
    "\n",
    "        out = self.res5b_2(out)\n",
    "\n",
    "        out += residual2  # res5b\n",
    "\n",
    "        out = self.res5b_bn(out)\n",
    "        out = self.res5b_relu(out)\n",
    "\n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ECO_3D(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(ECO_3D, self).__init__()\n",
    "\n",
    "        # 3D_Resnetジュール\n",
    "        self.res_3d_3 = Resnet_3D_3()\n",
    "        self.res_3d_4 = Resnet_3D_4()\n",
    "        self.res_3d_5 = Resnet_3D_5()\n",
    "\n",
    "        # Global Average Pooling\n",
    "        self.global_pool = nn.AvgPool3d(\n",
    "            kernel_size=(4, 7, 7), stride=1, padding=0)\n",
    "\n",
    "    def forward(self, x):\n",
    "        '''\n",
    "        入力xのサイズtorch.Size([batch_num,frames, 96, 28, 28]))\n",
    "        '''\n",
    "        out = torch.transpose(x, 1, 2)  # テンソルの順番入れ替え\n",
    "        out = self.res_3d_3(out)\n",
    "        out = self.res_3d_4(out)\n",
    "        out = self.res_3d_5(out)\n",
    "        out = self.global_pool(out)\n",
    "        \n",
    "        # テンソルサイズを変更\n",
    "        # torch.Size([batch_num, 512, 1, 1, 1])からtorch.Size([batch_num, 512])へ\n",
    "        out =out.view(out.size()[0], out.size()[1])\n",
    "        \n",
    "        return out\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 動作確認"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ECO_3D(\n",
       "  (res_3d_3): Resnet_3D_3(\n",
       "    (res3a_2): Conv3d(96, 128, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res3a_bn): BatchNorm3d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res3a_relu): ReLU(inplace)\n",
       "    (res3b_1): Conv3d(128, 128, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res3b_1_bn): BatchNorm3d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res3b_1_relu): ReLU(inplace)\n",
       "    (res3b_2): Conv3d(128, 128, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res3b_bn): BatchNorm3d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res3b_relu): ReLU(inplace)\n",
       "  )\n",
       "  (res_3d_4): Resnet_3D_4(\n",
       "    (res4a_1): Conv3d(128, 256, kernel_size=(3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
       "    (res4a_1_bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res4a_1_relu): ReLU(inplace)\n",
       "    (res4a_2): Conv3d(256, 256, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res4a_down): Conv3d(128, 256, kernel_size=(3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
       "    (res4a_bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res4a_relu): ReLU(inplace)\n",
       "    (res4b_1): Conv3d(256, 256, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res4b_1_bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res4b_1_relu): ReLU(inplace)\n",
       "    (res4b_2): Conv3d(256, 256, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res4b_bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res4b_relu): ReLU(inplace)\n",
       "  )\n",
       "  (res_3d_5): Resnet_3D_5(\n",
       "    (res5a_1): Conv3d(256, 512, kernel_size=(3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
       "    (res5a_1_bn): BatchNorm3d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res5a_1_relu): ReLU(inplace)\n",
       "    (res5a_2): Conv3d(512, 512, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res5a_down): Conv3d(256, 512, kernel_size=(3, 3, 3), stride=(2, 2, 2), padding=(1, 1, 1))\n",
       "    (res5a_bn): BatchNorm3d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res5a_relu): ReLU(inplace)\n",
       "    (res5b_1): Conv3d(512, 512, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res5b_1_bn): BatchNorm3d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res5b_1_relu): ReLU(inplace)\n",
       "    (res5b_2): Conv3d(512, 512, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))\n",
       "    (res5b_bn): BatchNorm3d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    (res5b_relu): ReLU(inplace)\n",
       "  )\n",
       "  (global_pool): AvgPool3d(kernel_size=(4, 7, 7), stride=1, padding=0)\n",
       ")"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# モデルの用意\n",
    "net = ECO_3D()\n",
    "net.train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. tensorboardXの保存クラスを呼び出します\n",
    "from tensorboardX import SummaryWriter\n",
    "\n",
    "# 2. フォルダ「tbX」に保存させるwriterを用意します\n",
    "# フォルダ「tbX」はなければ自動で作成されます\n",
    "writer = SummaryWriter(\"./tbX/\")\n",
    "\n",
    "\n",
    "# 3. ネットワークに流し込むダミーデータを作成します\n",
    "batch_size = 1\n",
    "dummy_img = torch.rand(batch_size, 16, 96, 28, 28)\n",
    "\n",
    "# 4. netに対して、ダミーデータである\n",
    "# dummy_imgを流したときのgraphをwriterに保存させます\n",
    "writer.add_graph(net, (dummy_img, ))\n",
    "writer.close()\n",
    "\n",
    "\n",
    "# 5. コマンドプロンプトを開き、フォルダtbXがあるフォルダまで移動して、\n",
    "# 以下のコマンドを実行します\n",
    "\n",
    "# tensorboard --logdir=\"./tbX/\"\n",
    "\n",
    "# その後、http://localhost:6006 にアクセスします\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以上"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
